/**
 * 定义一些业务层到数据层的映射策略
 */
package indi.zjh.dp.orm;

import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.dom4j.DocumentException;

import indi.zjh.dp.db.Configuration;
import indi.zjh.dp.db.TField;
import indi.zjh.dp.db.Table;
import indi.zjh.dp.error.UnsuportedFieldException;


public class BusinessMapDataStrategy {

	public static String getRelationTableName(RelationClass A, RelationClass B)
	{
		return getTableName(A) + "_" + getTableName(B);
	}
	// 业务模型到数据表的转换
	public static String getTableName(RelationClass rc)
	{
		return rc.getName().replace(".", "_").toLowerCase();
	}
	
	public static String getTableName(String clsname)
	{
		return clsname.replace(".", "_").toLowerCase();
	}
	
	public static String getRelationTableName(String a, String b)
	{
		return getTableName(a) + "_" + getTableName(b);
	}
	
//	public static TField getDataField(Field subject_field, String prefix)
//	{
//		TField tf = getDataField(subject_field);
//		
//		String[] ps = prefix.split("_");
//		StringBuffer sb = new StringBuffer();
//		for(int i = 0; i < ps.length; ++i)
//		{
//			sb.append("_");
//		}
//		tf.orgName = prefix + tf.name;
//		
//		tf.comment = "业务字段:" + prefix + tf.name;
//		//tf.name = sb.toString() + tf.name;
//		tf.name = prefix + tf.name;
//		
//		return tf;
//	}
	
	public static TField getDataField(Field f) throws InstantiationException, IllegalAccessException, NoSuchMethodException, SecurityException, IllegalArgumentException, InvocationTargetException
	{
		TField tf = new TField(f);
		tf.name = f.getName();
		
		Class<?> cls = f.getDeclaringClass();
		//Business obj = (Business)cls.newInstance();
		
		//tf.comment = obj.toDictString(f);
		Method method = cls.getMethod("toDictString", Field.class);
		
		tf.comment = (String)method.invoke(null, f);
		tf.orgName = tf.name;
		String typename = f.getType().getName();

		if(f.getName().equals("_id"))
			tf.isPrimary = true;
		
		if(typename.equals("java.lang.String"))
		{
			tf.type = TField.TYPE_STRING;
			tf.length = 32;
			tf.defaultValue = "nil";
		}
		else if(typename.equals("indi.zjh.dp.type.String64"))
		{
			tf.type = TField.TYPE_STRING;
			tf.length = 64;
			tf.defaultValue = "nil";
		}
		else if(typename.equals("indi.zjh.dp.type.String128"))
		{
			tf.type = TField.TYPE_STRING;
			tf.length = 128;
			tf.defaultValue = "nil";
		}
		else if(typename.equals("indi.zjh.dp.type.String256"))
		{
			tf.type = TField.TYPE_STRING;
			tf.length = 256;
			tf.defaultValue = "nil";
		}
		else if(typename.equals("int") || typename.equals("java.lang.Integer"))
		{
			tf.type = TField.TYPE_INT;
			tf.length = 4;
			tf.defaultValue = "0";
		}
		else if(typename.equals("short") || typename.equals("java.lang.Short"))
		{
			tf.type = TField.TYPE_SMALLINT;
			tf.length = 4;
			tf.defaultValue = "0";
		}
		else if(typename.equals("long") || typename.equals("java.lang.Long"))
		{
			tf.type = TField.TYPE_BIGINT;
			tf.length = 16;
			tf.defaultValue = "0";
		}
		else if(typename.equals("boolean") || typename.equals("java.lang.Boolean"))
		{
			tf.type = TField.TYPE_TINYINT;
			tf.length = 1;
			tf.defaultValue = "0";
		}
		else if(typename.equals("byte"))
		{
			tf.type = TField.TYPE_TINYINT;
			tf.length = 1;
			tf.defaultValue = "0";
		}
		else if(typename.equals("float") || typename.equals("java.lang.Float") || typename.equals("double") || typename.equals("java.lang.Double"))
		{
			tf.type = TField.TYPE_DECIMAL;
			tf.length = 4;
			tf.defaultValue = "0.0";
		}
		else if(typename.equals("java.util.Date"))
		{
			tf.type = TField.TYPE_DATETIME;
			tf.defaultValue = "";
		}
		else if(typename.equals("indi.zjh.dp.type.Text"))
		{
			tf.type = TField.TYPE_TEXT;
			tf.defaultValue = "";
		}
		else
		{
			tf.type = TField.TYPE_BLOB;
		}
		
		return tf;
	}
	
	
	
	public static List<TField> getDataField(Business obj) throws DocumentException, Exception
	{
		List<TField> ret = new ArrayList<TField>();
		// 获取业务基类字段
		RelationClass rc = Configuration.getInstance().getVersion().getRelationClass(obj.getClass().getName());
		Class<?> baseClass = Business.class;
		Field[] fields = baseClass.getDeclaredFields();
		for(int i = 0; i < fields.length; ++i)
		{
			if(fields[i].getName().startsWith("_"))
			{
				TField tf = BusinessMapDataStrategy.getDataField(fields[i]);
				ret.add(tf);
			}
		}
		
		List<Field> baseFields = rc.getBasicFields();
		Iterator<Field> iter = baseFields.iterator();
		while(iter.hasNext())
		{
			TField tf = BusinessMapDataStrategy.getDataField(iter.next());
			ret.add(tf);
		}

		return ret;
	}
	
	public static List<TField> getDataField(RelationClass rc) throws DocumentException, Exception
	{
		List<TField> ret = new ArrayList<TField>();
		Class<?> baseClass = Business.class;
		Field[] fields = baseClass.getDeclaredFields();
		for(int i = 0; i < fields.length; ++i)
		{
			if(fields[i].getName().startsWith("_"))
			{
				TField tf = BusinessMapDataStrategy.getDataField(fields[i]);
				ret.add(tf);
			}
		}
		
		List<Field> baseFields = rc.getBasicFields();
		Iterator<Field> iter = baseFields.iterator();
		while(iter.hasNext())
		{
			TField tf = BusinessMapDataStrategy.getDataField(iter.next());
			ret.add(tf);
		}
		
		
		return ret;
	}
	
	public static String getRelationCreateSql(RelationClass a, RelationClass b)
	{
		String tableName = getRelationTableName(a, b);
		Table t = new Table(tableName);
		TField tf = new TField();
		tf.name = "_id";
		tf.type = TField.TYPE_BIGINT;
		tf.defaultValue = "0";
		tf.field = null;
		tf.comment = "自增Id";
		tf.isPrimary = true;
		tf.length = 10;
		t.addField(tf);
		
		tf = new TField();
		tf.name = "aid";
		tf.type = TField.TYPE_BIGINT;
		tf.defaultValue = "0";
		tf.field = null;
		tf.comment = "主关联Id";
		tf.length = 10;
		t.addField(tf);
		
		tf = new TField();
		tf.name = "bid";
		tf.type = TField.TYPE_BIGINT;
		tf.defaultValue = "0";
		tf.field = null;
		tf.comment = "副关联Id";
		tf.length = 10;
		t.addField(tf);
		
		tf = new TField();
		tf.name = "_t";
		tf.type = TField.TYPE_INT;
		tf.defaultValue = "0";
		tf.field = null;
		tf.comment = "关联类型, 0-继承, 1-包含(组合), 2-聚合, 3-关联";
		tf.length = 2;
		t.addField(tf);
		
		t.setIgnore(false);
		return t.getCreateSql();
	}
	
	public static String[] getRelationTableIndexSql(RelationClass a, RelationClass b)
	{
		String[] sqls = new String[4];
		String tableName = getRelationTableName(a, b);
		int i = 0;
		
		if(Configuration.isMysql())
		{
			sqls[i++] = "ALTER TABLE `"+tableName+"` ADD INDEX `aid_index`(`aid`)";
			sqls[i++] = "ALTER TABLE `"+tableName+"` ADD INDEX `bid_index`(`bid`)";
			sqls[i++] = "ALTER TABLE `"+tableName+"` ADD INDEX `aid_bid_index`(`aid`, `bid`)";
			sqls[i++] = "ALTER TABLE `"+tableName+"` ADD UNIQUE `aid_bid_uindex`(`_t`, `aid`, `bid`)";
		}
		else
		{
			sqls[i++] = "CREATE INDEX `"+tableName+"aid_index` ON `"+tableName+"`(`aid`)";
			sqls[i++] = "CREATE INDEX `"+tableName+"bid_index` ON `"+tableName+"`(`bid`)";
			sqls[i++] = "CREATE INDEX `"+tableName+"aid_bid_index` ON `"+tableName+"`(`aid`, `bid`)";
			sqls[i++] = "CREATE UNIQUE INDEX `"+tableName+"aid_bid_uindex` on `"+tableName+"` (_t, aid, bid)";
		}
		
		return sqls;
	}
	
	/**
	 * 生成业务数据表sql语句
	 * @param obj
	 * @return
	 * @throws DocumentException
	 * @throws Exception
	 */
	public static String getCreateSql(Business obj) throws DocumentException, Exception
	{
		RelationClass rc = Configuration.getInstance().getVersion().getRelationClass(obj.getClass().getName());
		String tableName = BusinessMapDataStrategy.getTableName(rc);
		Table t = new Table(tableName);
		List<TField> fields = BusinessMapDataStrategy.getDataField(obj);
		t.addField(fields);
		return t.getCreateSql();
	}
//	
//	public static String getDeleteSql(Business obj) throws UnsuportedFieldException, DocumentException, Exception
//	{
//		RelationClass rc = Configuration.getInstance().getVersion().getRelationClass(obj.getClass().getName());
//		String tableName = BusinessMapDataStrategy.getTableName(rc);
//		return "UPDATE `"+tableName+"` SET `_deleted` = 1 WHERE `_id` = "+obj.getId();
//	}
//	
//	/**
//	 * 生成业务数据表插入sql语句
//	 * @param obj
//	 * @return
//	 * @throws DocumentException
//	 * @throws Exception
//	 */
//	public static String getInsertSql(Business obj) throws DocumentException, Exception
//	{
//		RelationClass rc = Configuration.getInstance().getVersion().getRelationClass(obj.getClass().getName());
//		String tableName = BusinessMapDataStrategy.getTableName(rc);
//		Table t1 = new Table(tableName);		
//		List<TField> fields = BusinessMapDataStrategy.getDataField(obj);
//		t1.addField(fields);
//		return t1.getInsertSql();
//	}
//	
//	/**
//	 * 生成业务数据表关系数据(继承,包含,关联)插入sql语句
//	 * @param rc
//	 * @return
//	 * @throws DocumentException
//	 * @throws Exception
//	 */
//	public static String getInsertSql(RelationClass rc) throws DocumentException, Exception
//	{
//		String tableName = BusinessMapDataStrategy.getTableName(rc);
//		Table t1 = new Table(tableName);		
//		List<TField> fields = BusinessMapDataStrategy.getDataField(rc);
//		t1.addField(fields);
//		return t1.getInsertSql();
//	}
//	
//	/**
//	 * 生成业务数据更新sql语句
//	 * @param obj
//	 * @return
//	 * @throws DocumentException
//	 * @throws Exception
//	 */
//	public static String getUpdateSql(Business obj) throws DocumentException, Exception
//	{
//		RelationClass rc = Configuration.getInstance().getVersion().getRelationClass(obj.getClass().getName());
//		String tableName = BusinessMapDataStrategy.getTableName(rc);
//		Table t1 = new Table(tableName);
//		Set<String> excludeFieldName = new HashSet<String>();
//		List<TField> fields = BusinessMapDataStrategy.getDataField(obj);
//		t1.addField(fields);
//		return t1.getUpdateSql();
//	}
	
//	/**
//	 * 生成业务数据表关系数据更新sql语句
//	 * @param obj
//	 * @param relate
//	 * @return
//	 * @throws DocumentException
//	 * @throws Exception
//	 */
//	public static String getUpdateSql(Business obj, RelationClass relate) throws DocumentException, Exception
//	{
//		String tableName = BusinessMapDataStrategy.getTableName(relate);
//		Table t1 = new Table(tableName);
//		List<TField> fields = BusinessMapDataStrategy.getDataField(relate);
//		t1.addField(fields);
//		return t1.getUpdateSql();
//	}
	
//	/**
//	 * 生成业务数据表查询sql语句
//	 * @param obj
//	 * @return
//	 * @throws DocumentException
//	 * @throws Exception
//	 */
//	public static String getSelectSql(Business obj) throws DocumentException, Exception
//	{
//		RelationClass rc = Configuration.getInstance().getVersion().getRelationClass(obj.getClass().getName());
//		String tableName = BusinessMapDataStrategy.getTableName(rc);
//		Table t1 = new Table(tableName);
//		List<TField> fields = BusinessMapDataStrategy.getDataField(obj);
//		t1.addField(fields);
//		rc.addFieldMap(fields);
//		return t1.getSelectSql();
//	}
	
//	/**
//	 * 生成业务数据表关系数据查询sql语句
//	 * @param obj
//	 * @param relate
//	 * @return
//	 * @throws DocumentException
//	 * @throws Exception
//	 */
//	public static String getSelectSql(Business obj, RelationClass relate) throws DocumentException, Exception
//	{
//		String tableName = BusinessMapDataStrategy.getTableName(relate);
//		Table t1 = new Table(tableName);
//		List<TField> fields = BusinessMapDataStrategy.getDataField(relate);
//		t1.addField(fields);
//		relate.addFieldMap(fields);
//		return t1.getSelectSql();
//	}
//	
//	public static List<Object> getObjectValue(Business obj) throws DocumentException, Exception
//	{
//		List<Object> values = new ArrayList<Object>();
//		List<TField> tFields = BusinessMapDataStrategy.getDataField(obj);
//		Iterator<TField> iter = tFields.iterator();
//		while(iter.hasNext())
//		{
//			Field f = iter.next().field;
//			if(f.getName().equals("_class"))
//			{
//				values.add(obj.getClass().getName());
//			}
//			else if(f.getName().equals("_id"))
//			{
//				values.add(obj.getSpecId(obj.getClass()));
//			}
//			else
//			{
//				f.setAccessible(true);
//				//values.add(f.get(obj));
//				values.add(BusinessMapDataStrategy.getFieldValue(obj, f));
//			}
//		}
//		return values;
//	}
//	
//	public static List<Object> getObjectValue(Business obj, RelationClass relate) throws DocumentException, Exception
//	{
//		List<Object> values = new ArrayList<Object>();
//		List<TField> tFields = BusinessMapDataStrategy.getDataField(relate);
//		Iterator<TField> iter = tFields.iterator();
//		RelationClass rc = Configuration.getInstance().getVersion().getRelationClass(obj.getClass().getName());
//		while(iter.hasNext())
//		{
//			Field f = iter.next().field;
//			if(f.getName().equals("_class"))
//			{
//				values.add(obj.getClass().getName());
//			}
//			else if(f.getName().equals("_id"))
//			{
//				// 如果是继承关系, 获取父类的对象Id
//				if(relate.isParentOf(rc))
//				{
//					values.add(obj.getSpecId(relate.getClazz()));
//				}
//				else
//				{
//					values.add(obj.getSpecId(obj.getClass()));
//				}
//			}
//			else if(f.getName().equals("_deleted"))
//			{
//				// 如果是继承关系, 同时删除父类对象
//				if(relate.isParentOf(rc))
//				{
//					if(obj.isDelete())
//						values.add(1);
//					else
//						values.add(0);
//				}
//				else
//				{
//					f.setAccessible(true);
//					//values.add(f.get(obj));
//					values.add(BusinessMapDataStrategy.getFieldValue(obj, f));
//				}
//			}
//			else
//			{
//				f.setAccessible(true);
//				//values.add(f.get(obj));
//				values.add(BusinessMapDataStrategy.getFieldValue(obj, f));
//			}
//		}
//		return values;
//	}
//
//	
//	public static void setObjectValue(Business obj, Map<String, Object> row) throws DocumentException, Exception
//	{
//		RelationClass rc = Configuration.getInstance().getVersion().getRelationClass(obj.getClass().getName());
//		Iterator<Map.Entry<String, Object>> iter = row.entrySet().iterator();
//		while(iter.hasNext())
//		{
//			Map.Entry<String, Object> entry = iter.next();
//			String tfieldName = entry.getKey();
//			Object val = entry.getValue();
//			TField tf = rc.getTFieldByName(tfieldName);
//			tf.field.setAccessible(true);
//			//tf.field.set(obj, val);
//			BusinessMapDataStrategy.setFieldValue(obj, tf.field, val);
//		}
//	}
//	
//	public static void setObjectValue(Business obj, RelationClass relate, Map<String, Object> row) throws DocumentException, Exception
//	{
//		Iterator<Map.Entry<String, Object>> iter = row.entrySet().iterator();
//		while(iter.hasNext())
//		{
//			Map.Entry<String, Object> entry = iter.next();
//			String tfieldName = entry.getKey();
//			Object val = entry.getValue();
//			TField tf = relate.getTFieldByName(tfieldName);
//			tf.field.setAccessible(true);
//			//tf.field.set(obj, val);
//			BusinessMapDataStrategy.setFieldValue(obj, tf.field, val);
//		}
//	}
//	
//	public static void setFieldValue(Business obj, Field f, Object v) throws IllegalArgumentException, IllegalAccessException
//	{
//		if(f.getType().getName().equals("double"))
//		{
//			java.math.BigDecimal dval = (java.math.BigDecimal)v;
//			f.set(obj, dval.doubleValue());
//		}
//		else
//		{
//			f.set(obj, v);
//		}
//	}
//	
//	public static Object getFieldValue(Business obj, Field f) throws IllegalArgumentException, IllegalAccessException
//	{
//		//System.out.println("getFieldValue "+f.getType().getName());
//		return f.get(obj);
//	}

	
}
